#include <functional>
#include <iostream>
#include <vector>
#include <list>
#include <stack>
#include <queue>
#include "stack.h"
#include "queue.h"
#include "priority_queue.h"

namespace test
{
void test_stack()
{
    stack<int, list<int>> st;
    st.push(1);
    st.push(2);
    st.push(3);
    st.push(4);

    while (!st.empty())
    {
        cout << st.top() << " ";
        st.pop();
    }
    cout << endl;
}

void test_queue()
{
    queue<int, list<int>> q;
    q.push(1);
    q.push(2);
    q.push(3);
    q.push(4);

    while (!q.empty())
    {
        cout << q.front() << " ";
        q.pop();
    }
    cout << endl;
}

void test_priority_queue()
{
    // priority_queue<int> pq;
    priority_queue<int, vector<int>, greater<int>> pq;
    pq.push(1);
    pq.push(2);
    pq.push(3);
    pq.push(4);
    pq.push(5);

    while (!pq.empty())
    {
        cout << pq.top() << " ";
        pq.pop();
    }
    cout << endl;
}

class date
{
    friend ostream& operator<<(ostream& _cout, const date& d);
public:
    date(int year = 1900, int month = 1, int day = 1)
        : _year(year)
        , _month(month)
        , _day(day)
    {}

    bool operator<(const date& d) const {
        return (_year < d._year)
               || (_year == d._year && _month < d._month)
               || (_year == d._year && _month == d._month && _day < d._day);
    }

    bool operator>(const date& d) const {
        return (_year > d._year)
               || (_year == d._year && _month > d._month)
               || (_year == d._year && _month == d._month && _day > d._day);
    }
private:
    int _year;
    int _month;
    int _day;
};

ostream& operator<<(ostream& _cout, const date& d) {
    return cout << d._year << "-" << d._month << "-" << d._day;
}

template<>
struct greater<date*>
{
    bool operator()(const date* p1, const date* p2)
    {
        return *p1 > *p2;
    }
};

void test_date()
{
    test::priority_queue<date> q1;
    q1.push(date(2020, 10, 29));
    q1.push(date(2020, 11, 28));
    q1.push(date(2022, 12, 30));
    cout << q1.top() << endl;

    test::priority_queue<date*, vector<date*>, greater<date*>> q2;
    q2.push(new date(2020, 10, 29));
    q2.push(new date(2020, 11, 28));
    q2.push(new date(2022, 12, 30));
    cout << *q2.top() << endl;
}

}

int main()
{
    // test::test_stack();
    // test::test_queue();
    // test::test_priority_queue();
    test::test_date();


    return 0;
}